package com.yangxc.core.log.aspect;

import com.alibaba.fastjson.JSONObject;
import com.yangxc.core.common.utils.RequestHolder;
import com.yangxc.core.common.utils.StringPool;
import com.yangxc.core.log.annotation.SysLog;
import com.yangxc.core.log.api.LogDto;
import com.yangxc.core.log.enums.LogTypeEnum;
import com.yangxc.core.log.service.LogService;
import com.yangxc.core.log.utils.LogUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Retention;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * @author yangxc
 * @version 1.0.0
 * @ClassName LogAspect.java
 * @Description TODO
 * @createTime 2021年06月24日 14:28:00
 */
@Slf4j
@Aspect
public class LogAspect {

    @Resource
    LogService logService;

    @SneakyThrows
    @Around("@annotation(sysLog)")
    public Object saveLog(ProceedingJoinPoint point, SysLog sysLog) {
        Object result = new Object();
        String strClassName = point.getTarget().getClass().getName();
        String strMethodName = point.getSignature().getName();
        log.info("[类名]:{},[方法]:{}", strClassName, strMethodName);

        HttpServletRequest httpServletRequest =  RequestHolder.getHttpServletRequest();
        String ip = RequestHolder.getHttpServletRequestIpAddress();
        // 打印执行时间
        long startTime = System.nanoTime();
        // 请求方法
        String method = httpServletRequest.getMethod();
        String url = httpServletRequest.getRequestURI();

        // 参数
        Object[] args = point.getArgs();
        String requestParam = getArgs(args, httpServletRequest);

        // 计算耗时
        long executeTime = 0L;
        LogDto logDto = LogUtil.getLogDto();
        try {
            result = point.proceed();
        } catch (Exception e){
            logDto.setType(LogTypeEnum.EXCEPTION.getType())
                    .setException(e.getMessage());
        }finally {
            executeTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
            logDto.setIp(ip).setMethod(method).setUrl(url).setExecuteTime(executeTime)
                    .setResult(String.valueOf(result)).setParams(requestParam)
                    .setTitle(sysLog.value());
            logService.save(logDto);
        }

        return result;
    }

    /**
     * 获取请求参数
     * @param args
     * @param request
     * @return
     */
    private String getArgs(Object[] args, HttpServletRequest request) {
        String strArgs = StringPool.EMPTY;

        try {
            if (!request.getContentType().contains("multipart/form-data")) {
                strArgs = JSONObject.toJSONString(args);
            }
        } catch (Exception e) {
            try {
                strArgs = Arrays.toString(args);
            } catch (Exception ex) {
                log.warn("解析参数异常", ex);
            }
        }
        return strArgs;
    }
}
